#include "tdomain.h"
#include "./ui_tdomain.h"
//#include <QVBoxLayout>
//#include <QMenu>
//#include <QStandardItemModel>
//#include <QMessageBox>
//#include <QInputDialog>
//#include <QLineEdit>
//#include <QDateTime>
//#include <QHeaderView>
//#include "domaindetailinfodlg.h"
//#include "clientsocket.h"
//#include <QThread>
//#include <QDialog>
//#include "domainwhoisdlg.h"
//#include "customtreecontrol.h"
//#include "domainquerydlg.h"
//#include "ctsocketrunnable.h"
//#include "domainquerytask.h"
//#include "clientsocket.h"
//#include "requesttask.h"
#include "dnsuffixwhoismappingdlg.h"
#include "dndictionarydlg.h"
#include "customdomaincreatedlg.h"
#include "global.h"
#include "dncategoryselectdlg.h"
#include "proxypool.h"
#include "proxymgrdlg.h"
#include "loaddomainquerytask.h"
//#include <QScrollBar>
#include "sqlitewriter.h"
#include "customheaderview.h"
//#include <QItemDelegate>

TDomain::TDomain(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::TDomain)
{
    //qDebug()<<QCoreApplication::applicationFilePath();
    ui->setupUi(this);
    initDb();

    setupUI();
    setupModels();
    createCategoryRightPopMenu();
    createDomainInfoRightPopMenu();
    initGlobalInfo();
    QThreadPool::globalInstance()->setMaxThreadCount(50);
    g_enableProxy = false;
//    m_threadPool = QThreadPool::globalInstance();
//    m_threadPool->setMaxThreadCount(50);


 //   m_dbMySql->getWhoisServerByDomainSuffix(m_suffixQryAddr);
//

}

TDomain::~TDomain()
{
    delete ui;
}

void TDomain::initGlobalInfo()
{
    m_dbMySql->getWhoisServerMappingDnSuffix(g_dnSuffixMappingWhoIs);
    QVector<ProxyServerData> vpsd = m_dbMySql->getProxyServers(1);
    g_proxyPool.proxies.clear();
    foreach (auto pd, vpsd) {
        g_proxyPool.proxies.append(pd.proxyaddr);
    }
    qDebug()<<"获取代理服务器数"<<g_proxyPool.proxies.size();

    g_dataDicts = m_dbMySql->getDataDict();
}

void TDomain::initDb()
{
    m_dbSqlLite = new DbManager();
    if(!m_dbSqlLite->initSqlite())
    {
        QMessageBox::information(this,"提示","sqlite连接失败");
        return;
    }

    m_dbMySql = new DbManager();
    m_dbMySql->m_mysqlConn = m_dbSqlLite->m_sqliteConn;//使用sqllite数据库
    //以下代码是切换mysql数据库
//    m_dbSqlLite->initCfgData();
//    m_dbMySql = new DbManager();
//    m_dbMySql->mySqlInfo =this->m_dbSqlLite->mySqlInfo;
//    if(!m_dbMySql->initMysql())
//    {
//        QMessageBox::information(this,"提示","mysql连接失败");
//        return;
//    }
}

void TDomain::setupUI()
{
    // 初始化视图控件并添加到布局中
//    m_treeView = new QTreeView(this);

//    m_tabTemplate = new TabulationTemplate(this);
//    //m_tableView = m_tabTemplate->m_tableView;

//    QHBoxLayout *layout = new QHBoxLayout;
//    layout->addWidget(m_treeView,1);
//    //layout->addWidget(m_tableView,3);
//    layout->addWidget(m_tabTemplate,4);

//    ui->centralwidget->setLayout(layout);

//    setCentralWidget(ui->centralwidget);
    m_treeView = ui->treeView;
    m_tableView = ui->tableView;

    // 连接垂直滚动条的释放信号
    connect(m_tableView->verticalScrollBar(), &QScrollBar::sliderReleased, this, &TDomain::onVerticalScrollStopped);
    // 连接水平滚动条的释放信号
    connect(m_tableView->horizontalScrollBar(), &QScrollBar::sliderReleased, this, &TDomain::onHorizontalScrollStopped);
    ui->progressBar->setRange(0,100);
    ui->progressBar->setValue(0);
    connect(m_tableView,SIGNAL(entered(QModelIndex)),this,SLOT(slotShowToolTip(QModelIndex)));
    connect(this,&TDomain::sigShowDnToTableView,this,&TDomain::ShowDnToTableView);
    ui->btn_stopQryDomain->setEnabled(false);
}
void TDomain::initCategory()
{
    m_dbMySql->loadCategoryTree(m_domainCategoryModel);
    if(m_domainCategoryModel->rowCount()==0)
    {
        qDebug()<<"new node";
        addNode(QModelIndex(), "未分类域名");
    }
    else
    {
        //qDebug()<<"have data";
        //读取数据库的节点信息，在qtreeview展示
    }
}

/*增删显示字段需要修改的地方：
1、数据库表domain_registry_info增删字段
2、TDomain::setupModels函数m_strColsName增删字段，位置按实际显示需要
3、publicstruct.h文件的DnSummaryInfo和DomainInfo结构增删字段，添加在最后
4、DbManager::getDomainRecByCategoryId函数
   修改strSql语句；while中添加新增字段赋值，添加在最后
5、在TDomain::refreshTableViewByCategoryId函数中
    rowItems.append(new QStandardItem(domainInfo.新增字段));注意顺序和第2步匹配
6、TDomain::dealRecvDataFromServer函数
    m_tableModel->item(row,2)->setText(dnInfo.Suffix);注意顺序和第2步匹配
7、DbManager::updateDomainDetailInfoById函数
    修改sql语句，新增赋值语句query.addBindValue(dnInfo.LastQryDate);


*/
void TDomain::setupModels()
{
    // 初始化域名类别模型
    m_domainCategoryModel = new QStandardItemModel;
    m_domainCategoryModel->setHorizontalHeaderLabels({"域名类别管理"});
    initCategory();
    m_treeView->setModel(m_domainCategoryModel);

    // 初始化域名详情模型
    m_tableModel = new QStandardItemModel;
    m_mainModel = new CtMainTableModel(this);

    m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);//行选中
    m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);//不可编辑
    // m_tableView->horizontalHeader()->setStyleSheet("QHeaderView::section {/*background-color:#1E90FF;*/font:10pt '微软雅黑';}");//标题栏样式
    m_tableView->horizontalHeader()->setFixedHeight(35);//标题栏行高
    m_tableView->verticalHeader()->setDefaultSectionSize(25);//设置列的行高
    m_strColsName<<"ID"<<"域名"<<"后缀"<<"注册状态"<<"上次查询日期"<<"注册商名称"<<"创建时间"<<"过期时间"<<"更新时间"<<"DNS服务器"<<"所有人名称"<<"所有人组织"<<"所有人国家"<<"所有人邮箱"<<"域名状态";

    //m_tableModel->setHorizontalHeaderLabels(m_strColsName);

    //m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    //m_tableView->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);

    //m_headerCheckbox = new QCheckBox("", m_tableView->horizontalHeader());
    //m_headerCheckbox->setStyleSheet("margin-left: 3px; margin-top: 10px;");
    //m_tableView->setModel(m_tableModel);

    //ui->tableView->setStyleSheet("");
    m_tableView->setModel(m_mainModel);
    //ui->tableView->setColumnWidth(0, 20); // 设置第一列的宽度
    // 使用自定义的水平头部
    CustomHeaderView *header = new CustomHeaderView(Qt::Horizontal, m_tableView);

    m_tableView->setHorizontalHeader(header);
    header->resizeSection(0, 10);
    connect(header, &CustomHeaderView::checkBoxStateChanged, this, &TDomain::toggleSelectAll);

    // m_tableView->setItemDelegateForColumn(0, new QItemDelegate(m_tableView)); // 使用默认委托
    // m_tableView->show();
    //m_tableView->verticalHeader()->setVisible(true);//放在setmodel之后
    // 表头全选复选框实现全选/全不选
//    connect(m_headerCheckbox, &QCheckBox::stateChanged, this, [&](int state) {
//        toggleSelectAll(state == Qt::Checked);
//    });

}

void TDomain::toggleAllSelected() {
    CustomHeaderView *header = static_cast<CustomHeaderView*>(m_tableView->horizontalHeader());
    QCheckBox *checkBox = findChild<QCheckBox*>(QString());
    bool isChecked = checkBox->isChecked();
    int totalRows = m_tableView->model()->rowCount();
    for (int row = 0; row < totalRows; ++row) {
        QModelIndex index = m_tableView->model()->index(row, 0);
        m_tableView->model()->setData(index, isChecked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
    }
    m_mainModel->toggleAllSelected(isChecked);
}

void TDomain::toggleSelectAll(bool checked)
{
    //qDebug()<<checked<<(m_headerCheckbox->checkState()==Qt::Checked);
    // CustomHeaderView *header = static_cast<CustomHeaderView*>(m_tableView->horizontalHeader());
    // QCheckBox *checkBox = findChild<QCheckBox*>(QString());
    // bool isChecked = checkBox->isChecked();
    // qDebug()<<checked<<isChecked;
    // int totalRows = m_mainModel->rowCount();
    // QModelIndex topLeftIndex,  bottomRightInde;
    // for (int row = 0; row < totalRows; ++row) {
    //     QModelIndex index = m_mainModel->index(row, 0);
    //     m_mainModel->setData(index, checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
    // }
    // topLeftIndex =  m_mainModel->index(0, 0);
    // bottomRightInde = m_mainModel->index(totalRows-1, 0);
    //m_mainModel->updateRangeData(topLeftIndex,bottomRightInde);
    m_mainModel->toggleAllSelected(checked);
}

void TDomain::onTextImpDomainRecs()
{
    QString m_strFileName = QFileDialog::getOpenFileName(this,"打开",QStandardPaths::writableLocation(QStandardPaths::DesktopLocation),"TXT 文件(*.txt)");
    if(m_strFileName.isEmpty())
    {
        //QMessageBox::information(this,"提示","打开文件路径失败"+m_strFileName);
        return;
    }
    QFile *pFile = new QFile(m_strFileName);
    if(!pFile->open(QIODevice::ReadOnly))
    {
        QMessageBox::information(this,"提示","打开文件失败");
        return;
    }

    // 创建文本流对象，便于读取文件内容
    QTextStream in(pFile);
    // 初始化QStringList用于存放处理后的行
    QStringList trimmedLines;
    // 逐行读取文件内容
    while (!in.atEnd()) {
        QString line = in.readLine();
        if(!line.isEmpty())
        {
            if(line.endsWith('\r'))
                line.chop(1);
            if(line.endsWith('\n'))
                line.chop(1);
            line = line.trimmed();
            trimmedLines.append(line);
            //qDebug()<<line;
        }
    }
    pFile->close();
    if(trimmedLines.length())
    {
        saveNewDomain(trimmedLines);
    }
}

void TDomain::onRuleCreateDomainRecs()
{
    //QSize dialogSize = size();
    QSize dialogSize = QSize(size().width() * 0.8, size().height() * 0.8);
    // 居中显示对话框
    QPoint centerPos = geometry().center() - QPoint(dialogSize.width() / 2, dialogSize.height() / 2);

    CustomDomainCreateDlg dlg(this);
    dlg.setWindowTitle("自定义域名创建");
    dlg.setFixedSize(dialogSize);
    dlg.move(centerPos);
    connect(&dlg, &CustomDomainCreateDlg::dataTransfer, this, [this](QStringList data) {saveNewDomain(data);});
    dlg.exec();
}
void TDomain::saveNewDomain(QStringList dnStrs)
{
    if(m_dbMySql->insertBatchDomainRecToSingleTables(g_undefineCategoryId,dnStrs))
    {
        QMessageBox::information(this,"提示","导入域名到【未分类域名】成功");
    }else
        QMessageBox::information(this,"提示","导入域名到【未分类域名】失败");
    //insertDomainRecToSingleTables
//    foreach(QString str, dnStrs) {
//        //qDebug() << str;
//        m_dbMySql->insertDomainRecToSingleTables(g_undefineCategoryId,str);
//    }

}


void TDomain::createCategoryRightPopMenu()
{
    // 为TreeView设置右键菜单
    m_contextMenu = new QMenu(this);
    m_rootMenu = new QMenu(this);

    QAction *addActionBrother = m_contextMenu->addAction("新建同级节点");
    addActionBrother->setIcon(QIcon(":Resource/icon/equalizer.svg"));
    QAction *addActionBrother1 = m_rootMenu->addAction("新建同级节点");
    addActionBrother1->setIcon(QIcon(":Resource/icon/equalizer.svg"));

    QAction *addActionChild = m_contextMenu->addAction("新建子节点");
    addActionChild->setIcon(QIcon(":Resource/icon/delete-two.svg"));
    QAction *delActionCurrent = m_contextMenu->addAction("删除当前节点");
    delActionCurrent->setIcon(QIcon(":Resource/icon/pic.svg"));
    QAction *updActionRename = m_contextMenu->addAction("重命名");
    updActionRename->setIcon(QIcon(":Resource/icon/tool.svg"));
    QAction *ActionReflesh = m_contextMenu->addAction("刷新");
    ActionReflesh->setIcon(QIcon(":Resource/icon/refresh.svg"));

    QAction *ActionReflesh1 = m_rootMenu->addAction("刷新");
    ActionReflesh1->setIcon(QIcon(":Resource/icon/refresh.svg"));

    connect(addActionBrother, &QAction::triggered, this, &TDomain::onAddBrotherCategory);
    connect(addActionBrother1, &QAction::triggered, this, &TDomain::onAddBrotherCategory);
    connect(addActionChild, &QAction::triggered, this, &TDomain::onAddChildCategory);
    connect(delActionCurrent, &QAction::triggered, this, &TDomain::onDeleteCurrentCategory);
    connect(updActionRename, &QAction::triggered, this, &TDomain::onRenameCategory);
    connect(ActionReflesh, &QAction::triggered, this, &TDomain::onRefleshCategoryTree);
    connect(ActionReflesh1, &QAction::triggered, this, &TDomain::onRefleshCategoryTree);

    // 关键在于在这里处理右键点击事件并显示菜单
    m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(m_treeView,SIGNAL(customContextMenuRequested(const QPoint &)),this, SLOT(slotCustomContextMenu(const QPoint &)));
    // 当部门节点选中时，更新表格数据
    connect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &TDomain::onCategorySelected);

}
void TDomain::slotCustomContextMenu(const QPoint &point)                     //槽函数定义
{
    QModelIndex index = m_treeView->indexAt(point);
    if (index.isValid()) {
        QModelIndex selectedIndex = m_treeView->selectionModel()->currentIndex();
        QString str = m_domainCategoryModel->itemFromIndex(selectedIndex)->text();
        qDebug()<<str;
        if(str=="未分类域名"||str=="全部记录")
        {
            m_rootMenu->popup(m_treeView->viewport()->mapToGlobal(point));
        }
        else
            m_contextMenu->popup(m_treeView->viewport()->mapToGlobal(point));
    }
}
QAction *TDomain::findActionByName(QMenu *menu, const QString &actionName)
{
    for (auto action : menu->actions()) {
        if (action->text() == actionName) {
            return action; // 直接找到匹配的 Action，返回
        }

        if (QMenu *subMenu = action->menu()) { // 将 QMenu* 存储在临时变量 subMenu 中
            QAction *nestedAction = findActionByName(subMenu, actionName);
            if (nestedAction) {
                return nestedAction; // 在子菜单中找到匹配的 Action，返回
            }
        }
    }

    return nullptr;
}


void TDomain::addNode(const QModelIndex &parentIndex, const QString &nodeName)
{
    if(nodeName.isEmpty())
        return;

    if (parentIndex.isValid())// 参数合法性检查
    {
        int parentId = m_domainCategoryModel->itemFromIndex(parentIndex)->data(Qt::UserRole ).toInt();
        //qDebug()<<"parentId"<<parentId;

        QString parentPath = m_dbMySql->getParentPath(parentId);
        int insertedId = m_dbMySql->insertCategoryNode(parentPath,nodeName);
        if(insertedId==-1)
            return;
        QStandardItem *parentItem = m_domainCategoryModel->itemFromIndex(parentIndex);
        QStandardItem *newItem = new QStandardItem(nodeName);
        newItem->setIcon(QIcon(":Resource/icon/bill.svg"));
        newItem->setData(insertedId, Qt::UserRole ); // 存储数据库ID
        parentItem->appendRow(newItem);

    }
    else
    {
        qDebug() << "创建新类别节点";
        //QString rootNodePath = "/";
        int insertedId = m_dbMySql->insertCategoryNode("",nodeName);
        if(insertedId==-1)
            return;
        // 将数据库变化反映到模型中
        QStandardItem *rootItem = new QStandardItem(nodeName);
        rootItem->setData(insertedId, Qt::UserRole );
        rootItem->setIcon(QIcon(":Resource/icon/bookmark-one.svg"));
        m_domainCategoryModel->appendRow(rootItem);
    }
}

void TDomain::onAddBrotherCategory()
{
    QModelIndex selectedIndex = m_treeView->selectionModel()->currentIndex();
    if (!selectedIndex.isValid()) {
        QMessageBox::warning(this, "警告", "请选择一个节点以添加同级节点！");
        return;
    }
    bool ok;
    QString newText = QInputDialog::getText(this,"编辑节点清单名称","请输入新的域名清单名称:",QLineEdit::Normal,"新节点",&ok);
    if (ok && !newText.isEmpty())
    {
        addNode(selectedIndex.parent(),newText);
    }
}

void TDomain::onAddChildCategory()
{
    QModelIndex selectedIndex = m_treeView->selectionModel()->currentIndex();
    if (!selectedIndex.isValid()) {
        QMessageBox::warning(this, "警告", "请选择一个节点以添加子节点！");
        return;
    }
    bool ok;
    QString newText = QInputDialog::getText(this,"编辑节点清单名称","请输入新的域名清单名称:",QLineEdit::Normal,"新节点",&ok);
    if (ok && !newText.isEmpty())
    {
        addNode(selectedIndex,newText);
        //m_treeView->setCurrentIndex(m_domainCategoryModel->index(selectedIndex.row() + 1, 0, selectedIndex.parent()));
    }
}

void TDomain::onDeleteCurrentCategory()
{
    QModelIndex selectedIndex = m_treeView->selectionModel()->currentIndex();
    if (!selectedIndex.isValid()) {
        QMessageBox::warning(this, "警告", "请选择一个节点以删除！");
        return;
    }
    QModelIndex parentIndex = selectedIndex.parent();


    QStandardItemModel *model = static_cast<QStandardItemModel*>(m_treeView->model());
    if(model->rowCount()==1&&!parentIndex.isValid())
    {
        QMessageBox::warning(this, "警告", "最后一个节点不可以删除！");
        return;
    }
    QStandardItem *tItem = model->itemFromIndex(selectedIndex);
    QString infostr = "是否要删除该节点："+tItem->text();
    if(tItem->text()=="未分类域名")
    {
        QMessageBox::warning(this, "警告", "该节点不可以删除！");
        return;
    }
    QMessageBox::StandardButton result= QMessageBox::question(this,"提示",infostr);
    if(result==QMessageBox::Yes)
    {
        m_dbMySql->deleteCategoryNode((tItem->data(Qt::UserRole).toInt()));
        model->removeRow(selectedIndex.row(), selectedIndex.parent());
    }
}

void TDomain::onRenameCategory()
{
    QModelIndex selectedIndex = m_treeView->selectionModel()->currentIndex();
    if (!selectedIndex.isValid()) {
        QMessageBox::warning(this, "警告", "请选择一个域名类别！");
        return;
    }

    QStandardItemModel *model = static_cast<QStandardItemModel *>(m_treeView->model());
    bool ok;
    QString newText = QInputDialog::getText(this,"编辑节点","请输入新的节点文本:",QLineEdit::Normal,model->itemFromIndex(selectedIndex)->text(),&ok);
    if (ok && !newText.isEmpty()) {
        QStandardItem *tItem = model->itemFromIndex(selectedIndex);
        tItem->setText(newText);
         //更新节点信息到数据库
        m_dbMySql->updateCategoryNode(tItem->data(Qt::UserRole).toInt(),newText);
    }
}

void TDomain::onRefleshCategoryTree()
{
//加载数据库的节点信息到qtreeview中
    m_domainCategoryModel->clear();
    m_domainCategoryModel->setHorizontalHeaderLabels({"域名类别管理"});
    m_dbMySql->loadCategoryTree(m_domainCategoryModel);
}

void TDomain::onCategorySelected()
{
    //selected.indexes()
    //qDebug()<<"onCategorySelected";
    QModelIndex currentSelection = m_treeView->selectionModel()->currentIndex();
    if (currentSelection.isValid())
    {
        QStandardItem *selectItem = m_domainCategoryModel->itemFromIndex(currentSelection);
        if(!selectItem->hasChildren())
        {
            int categoryId = selectItem->data(Qt::UserRole).toInt();
            //qDebug()<<categoryId;
            refreshTableViewByCategoryId(categoryId,"","","","");
        }
    }
}
void TDomain::refreshTableViewByCategoryId(int categoryId,QString filterSuffix,QString filterDnStatus,QString filterExpDate,QString filterRegStatus)
{
    //qDebug()<<categoryId<<filterSuffix<<filterDnStatus<<filterExpDate;
    m_tableModel->removeRows(0,m_tableModel->rowCount());
    m_mainModel->clearData();
    QList<DnSummaryInfo> diList = m_dbMySql->getDomainRecByCategoryId(categoryId,filterSuffix,filterDnStatus,filterExpDate,filterRegStatus);
    if(diList.size()==0)
    {
        qDebug()<<"该域名类别无数据"<<categoryId<<filterSuffix<<filterDnStatus<<filterExpDate;
        return;
    }
    QStringList strsuffix;
    for (const DnSummaryInfo &domainInfo : diList) {
        QList<QStandardItem *> rowItems ;
        QStandardItem * it = new QStandardItem(QString::number(domainInfo.id));
       // it->setCheckable(true);
       // it->setFlags(it->flags() | Qt::ItemIsUserCheckable);
        rowItems.append(new QStandardItem(""));
        rowItems.append(it);
        rowItems.append(new QStandardItem(domainInfo.domain));
        strsuffix.append(domainInfo.suffix);
        rowItems.append(new QStandardItem(domainInfo.suffix));
        rowItems.append(new QStandardItem(domainInfo.registStatus));
        rowItems.append(new QStandardItem(domainInfo.lastQryDate));
        rowItems.append(new QStandardItem(domainInfo.registrar));
        rowItems.append(new QStandardItem(domainInfo.creationDate));
        rowItems.append(new QStandardItem(domainInfo.expiryDate));
        rowItems.append(new QStandardItem(domainInfo.updatedDate));
        rowItems.append(new QStandardItem(domainInfo.nameServer));
        rowItems.append(new QStandardItem(domainInfo.registrant));
        rowItems.append(new QStandardItem(domainInfo.registrantOrg));
        rowItems.append(new QStandardItem(domainInfo.registrantCountry));
        rowItems.append(new QStandardItem(domainInfo.registrantEmail));
        rowItems.append(new QStandardItem(domainInfo.domainStatus));

        m_tableModel->appendRow(rowItems);
        m_mainModel->addData(domainInfo);
    }
    QSet<QString> uniqueSet(strsuffix.begin(), strsuffix.end()); // 使用QSet去除重复项
    QStringList uniqueList(uniqueSet.begin(), uniqueSet.end()); // 将QSet转换回QStringList
    ui->cb_suffix->clear();
    ui->cb_suffix->addItem("无限制");
    ui->cb_suffix->addItems(uniqueList);
}
void TDomain::refreshTableViewByDnId(QString dnIds)
{
    //m_tableModel->removeRows(0,m_tableModel->rowCount());
    //m_mainModel->clearData();
    QList<DnSummaryInfo> diList = m_dbMySql->getDomainRecByDnIds(dnIds );
    if(diList.size()==0)
    {
        qDebug()<<"该域名类别无数据"<<dnIds;
        return;
    }

    QStringList strsuffix;
    int row;
    QModelIndex index;
    for (const DnSummaryInfo &domainInfo : diList) {

        row = m_mainModel->findItemsIdxByDnId(domainInfo.id);
        if(row==-1)
        {
            qDebug() << "找不到指定的域名信息" << domainInfo.id;
            continue;
        }

        index = m_mainModel->index(row, 1);
        m_mainModel->setData(index,QVariant(domainInfo.domain));
         index = m_mainModel->index(row, 2);
         m_mainModel->setData(index,QVariant(domainInfo.suffix));
         index = m_mainModel->index(row, 3);
         m_mainModel->setData(index,QVariant(domainInfo.registStatus));
         index = m_mainModel->index(row, 4);
         m_mainModel->setData(index,QVariant(domainInfo.lastQryDate));
         index = m_mainModel->index(row, 5);
         m_mainModel->setData(index,QVariant(domainInfo.registrar));
         index = m_mainModel->index(row, 6);
         m_mainModel->setData(index,QVariant(domainInfo.creationDate));
         index = m_mainModel->index(row, 7);
         m_mainModel->setData(index,QVariant(domainInfo.expiryDate));
         index = m_mainModel->index(row, 8);
         m_mainModel->setData(index,QVariant(domainInfo.updatedDate));
         index = m_mainModel->index(row, 9);
         m_mainModel->setData(index,QVariant(domainInfo.nameServer));
         index = m_mainModel->index(row, 10);
         m_mainModel->setData(index,QVariant(domainInfo.registrant));
         index = m_mainModel->index(row, 10);
         m_mainModel->setData(index,QVariant(domainInfo.registrantOrg));
         index = m_mainModel->index(row, 10);
         m_mainModel->setData(index,QVariant(domainInfo.registrantCountry));
         index = m_mainModel->index(row, 10);
         m_mainModel->setData(index,QVariant(domainInfo.registrantEmail));
         index = m_mainModel->index(row, 10);
         m_mainModel->setData(index,QVariant(domainInfo.domainStatus));
         //qDebug()<<domainInfo.id<<domainInfo.domainStatus;
    }
}
void TDomain::on_actionDomainDic_triggered()
{
    // 设置对话框的大小
    QSize dialogSize = QSize(size().width() * 0.8, size().height() * 0.8);
    // 居中显示对话框
    QPoint centerPos = geometry().center() - QPoint(dialogSize.width() / 2, dialogSize.height() / 2);
    DnDictionaryDlg dlg(this);
    dlg.setWindowTitle("域名字典");
    dlg.setFixedSize(dialogSize);
    dlg.move(centerPos);
    dlg.exec();
}


void TDomain::on_actionCreateDomain_triggered()
{
    onRuleCreateDomainRecs();
}


void TDomain::on_actionDomainWhois_triggered()
{
    // 设置对话框的大小
    QSize dialogSize = QSize(size().width() * 0.8, size().height() * 0.8);
    // 居中显示对话框
    QPoint centerPos = geometry().center() - QPoint(dialogSize.width() / 2, dialogSize.height() / 2);
    DNSuffixWhoisMappingDlg dlg(this);
    dlg.setWindowTitle("域名与WhoIS服务映射");
    dlg.setFixedSize(dialogSize);
    dlg.move(centerPos);
    dlg.exec();
}


void TDomain::on_actionQryDomain_triggered()
{
    //onRuleCreateDomainRecs();
    // 设置对话框的大小
//    QSize dialogSize = QSize(size().width() * 0.8, size().height() * 0.8);
//    // 居中显示对话框
//    QPoint centerPos = geometry().center() - QPoint(dialogSize.width() / 2, dialogSize.height() / 2);

//    DomainQueryDlg *pdlg = new DomainQueryDlg(this);
//    pdlg->setAttribute(Qt::WA_DeleteOnClose);//自动销毁
//    pdlg->setWindowTitle("域名查询");
//    pdlg->setFixedSize(dialogSize);
//    pdlg->move(centerPos);
//    pdlg->show();
}


void TDomain::on_actionAnalysisDomain_triggered()
{
    QMessageBox::information(this, tr("提示"), tr("还没做."));
}


void TDomain::on_actionConcernDomain_triggered()
{
    QMessageBox::information(this, tr("提示"), tr("还没做."));
}



void TDomain::on_actionExit_triggered()
{
    this->close();
}




void TDomain::queryDomainWhois(QString dnStr)
{
    qDebug()<<__FUNCTION__;
//    QString suffix = dnStr.section('.',1,-1);
//    QString addrStr;
//    int port;
//    //qDebug()<<suffix;
//    QStringList strWhois = g_dnSuffixMappingWhoIs["."+suffix];
//    if(strWhois.size()==0)
//    {
//        qDebug()<<"无法查找到匹配的域名服务器!"<<dnStr;
//        return;
//    }

//    addrStr=strWhois.at(0);
//    port = strWhois.at(1).toInt();
//    qDebug()<<"发送查询请求"<<addrStr<<port<<dnStr;

//    ClientSocket *clientSocket = new ClientSocket();
//    clientSocket->m_sendMsg = dnStr;
//    clientSocket->m_flag = dnStr;
//    QThread *socketThread = new QThread;

//    clientSocket->moveToThread(socketThread);

//    connect(socketThread, &QThread::started, clientSocket, [=](){clientSocket->startConnection(addrStr,port);});
//    connect(socketThread, &QThread::finished, socketThread, &QThread::deleteLater);
//    connect(socketThread, &QThread::finished, clientSocket, &QObject::deleteLater);

//    connect(clientSocket, &QObject::destroyed, socketThread, &QThread::quit);
//    // connect(clientSocket, &ClientSocket::socketError, this, [](QAbstractSocket::SocketError error) { /* 错误处理 */ });

//    connect(clientSocket, &ClientSocket::dataReceived, this, &TDomain::dealRecvDataFromServer);
//    socketThread->start();
//    qDebug()<<"socket thread start"<<dnStr;
}

void TDomain::dealRecvDataFromServer(QByteArray data,QString reqParam)
{
    m_pgBarCurrent++;
    float fraction =100* m_pgBarCurrent / m_pgBarTotal;
    int prvalue =  qRound(fraction);

    //qDebug() << "返回值"<<m_pgBarCurrent<<m_pgBarTotal;
    ui->progressBar->setValue(prvalue);


    qDebug()<<__FUNCTION__<<QThread::currentThreadId()<<"dealRecvDataFromServer"<<reqParam<<data.length();//<<data;
    if(data.length()==0)
    {
        qDebug()<<"查询异常!"<<reqParam;
        return;
    }

    QMap<QString, QString> infoMaps;
    QString suffix = "."+reqParam.section('.',1,-1);
    QStringList strWhois = g_dnSuffixMappingWhoIs[suffix];
    if(strWhois.size()==0)
    {
        qDebug()<<"无法查找到匹配的域名服务器!"<<reqParam;
        return ;
    }
    int dnType = strWhois.at(2).toInt();

    infoMaps = decodeWhoisInfoToMap(dnType,data);
    if(infoMaps.size()==0)
    {
        qDebug()<<"域名查询返回数据解析失败"<<reqParam<<data;
        return;
    }
    //根据flag匹配m_tableModel中的记录
    QList<QStandardItem*> foundLst = m_tableModel->findItems(reqParam, Qt::MatchExactly, 1);
    if(foundLst.size()<1)
    {
        qDebug() << "找不到指定的域名信息" << reqParam;
        return;
    }

    QStandardItem* item = foundLst.at(0);
    int row = item->row();
    QModelIndex index = m_tableModel->index(row, 0);
    int domainId = index.data(Qt::DisplayRole).toInt();
    QString domainStr =item->data(Qt::DisplayRole).toString();
    //m_strColsName<<"ID"<<"域名"<<"后缀"<<"注册商名称"<<"创建时间"<<"过期时间"<<"更新时间"<<"DNS服务器"<<"所有人名称"<<"所有人组织"<<"所有人国家"<<"所有人邮箱"<<"域名状态";
    DomainInfo dnInfo;

    if(dnType==1)//以/r/n分行
    {
        dnInfo.Id=domainId;
        dnInfo.CategoryId=domainId;
        dnInfo.Domain=infoMaps["Domain Name"];
        dnInfo.Suffix=suffix;
        dnInfo.RegistStatus = infoMaps["Regist Status"];
        dnInfo.RegistryDomainID=infoMaps["Registry Domain ID"];
        dnInfo.RegistrarWHOISServer=infoMaps["Registrar WHOIS Server"];
        dnInfo.RegistrarURL=infoMaps["Registrar URL"];
        dnInfo.UpdatedDate=infoMaps["Updated Date"];
        dnInfo.CreationDate=infoMaps["Creation Date"];
        dnInfo.RegistryExpiryDate=infoMaps["Registry Expiry Date"];
        dnInfo.Registrar=infoMaps["Registrar"];
        dnInfo.RegistrarIANAID=infoMaps["Registrar IANA ID"];
        dnInfo.RegistrarEmail=infoMaps["Registrar Abuse Contact Email"];
        dnInfo.RegistrarPhone=infoMaps["Registrar Abuse Contact Phone"];
        dnInfo.RegistryRegistrantID=infoMaps["Registry Registrant ID"];
        dnInfo.RegistrantName=infoMaps["Registrant Name"];
        dnInfo.RegistrantOrganization=infoMaps["Registrant Organization"];
        dnInfo.RegistrantStreet=infoMaps["Registrant Street"];
        dnInfo.RegistrantCity=infoMaps["Registrant City"];
        dnInfo.RegistrantStateProvince=infoMaps["Registrant State/Province"];
        dnInfo.RegistrantPostalCode=infoMaps["Registrant Postal Code"];
        dnInfo.RegistrantCountry=infoMaps["Registrant Country"];
        dnInfo.RegistrantPhone=infoMaps["Registrant Phone"];
        dnInfo.RegistrantFax=infoMaps["Registrant Fax"];
        dnInfo.RegistrantEmail=infoMaps["Registrant Email"];
        dnInfo.NameServer=infoMaps["Name Server"];
        dnInfo.DomainStatus=infoMaps["Domain Status"];
        dnInfo.DNSSEC=infoMaps["DNSSEC"];
    }
    else//以/n分行
    {

        dnInfo.Id=domainId;
        dnInfo.CategoryId=domainId;
        dnInfo.Domain=infoMaps["Domain Name"];
        dnInfo.Suffix=suffix;
        dnInfo.RegistStatus = infoMaps["Regist Status"];
        dnInfo.RegistryDomainID=infoMaps["Registry Domain ID"];
        dnInfo.RegistrarWHOISServer=infoMaps["Registrar WHOIS Server"];
        dnInfo.RegistrarURL=infoMaps["Registrar URL"];
        dnInfo.UpdatedDate=infoMaps["Registration Time"];
        dnInfo.CreationDate=infoMaps["Registration Time"];
        dnInfo.RegistryExpiryDate=infoMaps["Expiration Time"];
        dnInfo.Registrar=infoMaps["Sponsoring Registrar"];
        dnInfo.RegistrarIANAID=infoMaps["Registrar IANA ID"];
        dnInfo.RegistrarEmail=infoMaps["Registrar Abuse Contact Email"];
        dnInfo.RegistrarPhone=infoMaps["Registrar Abuse Contact Phone"];
        dnInfo.RegistryRegistrantID=infoMaps["Registry Registrant ID"];
        dnInfo.RegistrantName=infoMaps["Registrant"];
        dnInfo.RegistrantOrganization=infoMaps["Registrant Organization"];
        dnInfo.RegistrantStreet=infoMaps["Registrant Street"];
        dnInfo.RegistrantCity=infoMaps["Registrant City"];
        dnInfo.RegistrantStateProvince=infoMaps["Registrant State/Province"];
        dnInfo.RegistrantPostalCode=infoMaps["Registrant Postal Code"];
        dnInfo.RegistrantCountry=infoMaps["Registrant Country"];
        dnInfo.RegistrantPhone=infoMaps["Registrant Phone"];
        dnInfo.RegistrantFax=infoMaps["Registrant Fax"];
        dnInfo.RegistrantEmail=infoMaps["Registrant Email"];
        dnInfo.NameServer=infoMaps["Registrar"];
        dnInfo.DomainStatus=infoMaps["Name Server"];
        dnInfo.DNSSEC=infoMaps["DNSSEC"];

    }
    QDate currentDate = QDate::currentDate();
    dnInfo.LastQryDate = currentDate.toString("yyyy-MM-dd");
//    "ID"<<"域名"<<"后缀"<<"注册状态"<<"注册商名称"<<"创建时间"<<"过期时间"<<"更新时间"<<"DNS服务器"<<"所有人名称"<<"所有人组织"<<"所有人国家"<<"所有人邮箱"<<"域名状态";
    //qDebug()<<"444";
//    m_tableModel->item(row,2)->setText(dnInfo.Suffix);//后缀
//    m_tableModel->item(row,3)->setText(dnInfo.RegistStatus);//注册状态
//    QDate currentDate = QDate::currentDate();
//    dnInfo.LastQryDate=currentDate.toString("yyyy-MM-dd");
//    m_tableModel->item(row,4)->setText(dnInfo.LastQryDate);//注册状态
//    m_tableModel->item(row,5)->setText(dnInfo.Registrar);//注册商名称
//    m_tableModel->item(row,6)->setText(dnInfo.CreationDate.left(10));//创建时间
//    m_tableModel->item(row,7)->setText(dnInfo.RegistryExpiryDate.left(10));//过期时间
//    m_tableModel->item(row,8)->setText(dnInfo.UpdatedDate.left(10));//更新时间
//    m_tableModel->item(row,9)->setText(dnInfo.NameServer);//DNS服务器
//    m_tableModel->item(row,10)->setText(dnInfo.RegistrantName);//所有人名称
//    m_tableModel->item(row,11)->setText(dnInfo.RegistrantOrganization);//所有人组织
//    m_tableModel->item(row,12)->setText(dnInfo.RegistrantCountry);//所有人国家
//    m_tableModel->item(row,13)->setText(dnInfo.RegistrantEmail);//所有人邮箱
//    m_tableModel->item(row,14)->setText(dnInfo.DomainStatus);//域名状态
    //qDebug()<<"updateDomainDetailInfoById-1"<<domainStr;
    m_dbMySql->updateDomainDetailInfoById(domainId, domainStr, dnInfo);
    qDebug()<<"updateDomainDetailInfoById-2"<<domainStr;
    //emit sigShowDnToTableView(row,dnInfo);
}

QMap<QString, QString> TDomain::decodeWhoisInfoToMap(int dnType, QByteArray data)
{
//    QString suffix = dnStr.section('.',1,-1);
    QString separator,bufStr;
    QMap<QString, QString> infoMaps;
    bufStr = data;
    //qDebug()<<suffix;
//    QStringList strWhois = g_dnSuffixMappingWhoIs["."+suffix];
//    if(strWhois.size()==0)
//    {
//        qDebug()<<"无法查找到匹配的域名服务器!"<<dnStr;
//        return infoMaps;
//    }
    //清除DNSSEC: unsigned之后的无效数据
    int index = bufStr.indexOf("DNSSEC");
    if(index==-1)
    {
        qDebug()<<"域名未注册,没有DNSSEC信息.";
        infoMaps["Regist Status"]="未注册";
    }
    else
    {
        //    if (index >= 0)//把DNSSEC: unsigned内容包进来
        //        bufStr = bufStr.left(index+16);

        if(dnType==1)
            separator = "\r\n";
        else
            separator = "\n";
        //qDebug()<<bufStr;
        QStringList domainStrings = bufStr.split(separator);

        //QVector<QString> statusVectors, nameServerVectors;
        QString sv,nsv;
        QString keystr, valstr;

        for (int i = 0; i < domainStrings.size(); i++) {
            //qDebug()<<domainStrings.at(i);

            QStringList infoStrings = domainStrings.at(i).split(": ");
            if(infoStrings.size()<1)
            {
                qDebug() << "接收数据异常: " << domainStrings.at(i);
                infoMaps.clear();
                return infoMaps;
            }
            keystr = infoStrings.at(0).trimmed();
            if(infoStrings.size()==2)
                valstr = infoStrings.at(1).left(127);
            else
                valstr="";
            if(valstr=="REDACTED FOR PRIVACY"||valstr.contains("Please query the WHOIS"))
                valstr="";

            if (keystr == "Domain Status") {
                //statusVectors.append(valstr);
                QStringList astr = valstr.split(" ");
                sv+=astr.at(0);
                sv+=";";
                infoMaps[keystr]=sv;
            } else if (keystr == "Name Server") {
                //nameServerVectors.append(valstr);
                nsv+=valstr;
                nsv+=";";
                infoMaps[keystr]=nsv;
            } else {
                infoMaps[keystr] = valstr;
            }
            //qDebug() << keystr << valstr;
            if (keystr.trimmed() == "DNSSEC")
                break;
        }
        //qDebug() << "成功接收数据" << infoMaps.size()<<dnStr;//<<infoMaps;
        infoMaps["Regist Status"]="已注册";
    }
    return infoMaps;
}

void TDomain::on_btn_query_clicked()
{

    QModelIndex currentSelection = m_treeView->selectionModel()->currentIndex();
    if (!currentSelection.isValid())
    {
        QMessageBox::information(this,"提示","请选择域名类别");
        return;
    }
    QStandardItem *selectItem = m_domainCategoryModel->itemFromIndex(currentSelection);
    if(selectItem->hasChildren())
    {
        QMessageBox::information(this,"提示","请选择子域名类别");
        return;
    }

    int categoryId = selectItem->data(Qt::UserRole).toInt();
    //qDebug()<<categoryId;
    QString dnStatusfilter = ui->cb_dnStatus->currentText();
    if(dnStatusfilter=="无限制")
    {
        dnStatusfilter ="";
    }

    QString dnSuffixfilter = ui->cb_suffix->currentText();
    if(dnSuffixfilter=="无限制")
    {
        dnSuffixfilter="";
    }
    QString dnRegStatusfilter = ui->cb_registerStatus->currentText();
    if(dnRegStatusfilter=="无限制")
    {
        dnRegStatusfilter="";
    }
    QString expDatefilter = ui->cb_expDate->currentText();
    if(expDatefilter=="无限制")
    {
        expDatefilter="";
    }
    else
    {
        QDate currentDate = QDate::currentDate();
        QString strDate;
        if(expDatefilter=="1周内"){
            strDate=currentDate.addDays(7).toString("yyyy-MM-dd");

        }else if(expDatefilter=="2周内"){
            strDate=currentDate.addDays(14).toString("yyyy-MM-dd");
        }else if(expDatefilter=="1个月内"){
            strDate=currentDate.addDays(30).toString("yyyy-MM-dd");
        }else if(expDatefilter=="3个月内"){
            strDate=currentDate.addDays(90).toString("yyyy-MM-dd");
        }else if(expDatefilter=="6个月内"){
            strDate=currentDate.addDays(180).toString("yyyy-MM-dd");
        }else{
            strDate=currentDate.toString("yyyy-MM-dd");
        }
        expDatefilter = strDate;
    }
    refreshTableViewByCategoryId(categoryId,dnSuffixfilter,dnStatusfilter,expDatefilter,dnRegStatusfilter);
}


void TDomain::on_btn_reset_clicked()
{
    ui->cb_dnStatus->setCurrentText("无限制");
    ui->cb_suffix->setCurrentText("无限制");
    ui->cb_expDate->setCurrentText("无限制");
}

void TDomain::createDomainInfoRightPopMenu()
{
    m_domainInfoMenu = new QMenu(this);
    m_addDomainsMenu = new QMenu(this);

    QString menuStyle = "QMenu::item {""color: black; /* 设置菜单项文字颜色 */""}"
                        "QMenu::item:selected {""background-color: #87CEEB; /* 设置被选中菜单项的背景色 */""}"
                        "QMenu::separator {""height: 1px; /* 可选：设置分隔线高度 */""background-color: #777; /* 可选：设置分隔线颜色 */""}";

    //"QMenu {""background-color: #FFF5EE; /* 设置菜单整体背景色 */""}"

    m_domainInfoMenu->setStyleSheet(menuStyle);
    m_addDomainsMenu->setStyleSheet(menuStyle);

    QAction* textImport = m_addDomainsMenu->addAction("文本导入");
    textImport->setIcon(QIcon(":Resource/icon/save-one.svg"));
    connect(textImport, &QAction::triggered, this, &TDomain::onTextImpDomainRecs);

    QAction* ruleCreate = m_addDomainsMenu->addAction("规则生成");
    ruleCreate->setIcon(QIcon(":Resource/icon/rss.svg"));
    connect(ruleCreate, &QAction::triggered, this, &TDomain::onRuleCreateDomainRecs);

    QAction* addDomains = m_domainInfoMenu->addAction("添加域名");
    addDomains->setIcon(QIcon(":Resource/icon/tag-one.svg"));
    addDomains->setMenu(m_addDomainsMenu);
/*-----------------------------------------------------------------------------*/
    QAction *qryWhois = m_domainInfoMenu->addAction("Whois查询");
    qryWhois->setIcon(QIcon(":Resource/icon/setting-one.svg"));


    connect(qryWhois, &QAction::triggered, this, &TDomain::onQryDomainWhois);



 /*-----------------------------------------------------------------------------*/
    QAction *setDomainsCategory = m_domainInfoMenu->addAction("域名归类");
    setDomainsCategory->setIcon(QIcon(":Resource/icon/system.svg"));
    connect(setDomainsCategory, &QAction::triggered, this, &TDomain::onsetDomainsCategory);

    QAction *delDomainsInfo = m_domainInfoMenu->addAction("域名删除");
    delDomainsInfo->setIcon(QIcon(":Resource/icon/system.svg"));
    connect(delDomainsInfo, &QAction::triggered, this, &TDomain::onDelCurrentRec);

    QAction *refDomainsInfo = m_domainInfoMenu->addAction("刷新");
    refDomainsInfo->setIcon(QIcon(":Resource/icon/equalizer.svg"));
    connect(refDomainsInfo, &QAction::triggered, this, &TDomain::onRefleshDomainTable);

//    QAction *qryDns = m_domainInfoMenu->addAction("查询DNS");
//    qryDns->setIcon(QIcon(":Resource/icon/home.svg"));
//    connect(qryDns, &QAction::triggered, this, &TabulationTemplate::onQryDomainDns);

//    QAction *qryNetServer = m_domainInfoMenu->addAction("查询网络服务信息");
//    qryNetServer->setIcon(QIcon(":Resource/icon/lightning.svg"));
//    connect(qryNetServer, &QAction::triggered, this, &TabulationTemplate::onQryDomainNetServer);

//    QAction *qryPrice = m_domainInfoMenu->addAction("查询价格");
//    qryPrice->setIcon(QIcon(":Resource/icon/loading.svg"));
//    connect(qryPrice, &QAction::triggered, this, &TabulationTemplate::onQryDomainPrice);

    // 关键在于在这里处理右键点击事件并显示菜单
    m_tableView->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(m_tableView,SIGNAL(customContextMenuRequested(const QPoint &)),this, SLOT(slotDomainInfoPopMenu(const QPoint &)));
    connect(m_tableView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(slotRowDoubleClicked(const QModelIndex &)));

}

void TDomain::slotDomainInfoPopMenu(const QPoint &point)                     //槽函数定义
{
    //m_domainInfoMenu->exec(QCursor::pos());
    QModelIndex index = m_tableView->indexAt(point);
    if (index.isValid()) {
        m_domainInfoMenu->popup(m_tableView->viewport()->mapToGlobal(point));
    }
    //m_domainInfoMenu->popup(m_tableView->viewport()->mapToGlobal(point));
}



void TDomain::slotRowDoubleClicked(const QModelIndex index)
{
    QModelIndex selectedIndex = m_tableView->selectionModel()->currentIndex();
    if (!selectedIndex.isValid()) {
        return;
    }

    QStandardItem *itemId = m_tableModel->item(selectedIndex.row(),0);
    int recId = itemId->text().toInt();
//    DomainDetailInfo ddi = getDomainDetailInfoById(recId);

//    QSize mainWindowSize = size();
//    QSize dialogSize = QSize(mainWindowSize.width() * 0.8, mainWindowSize.height() * 0.8);
//    DomainDetailInfoDlg dlg;
//    // 设置对话框的大小
//    dlg.setFixedSize(dialogSize);

//    // 居中显示对话框
//    QRect screenGeometry = geometry();
//    QPoint centerPos = screenGeometry.center() - QPoint(dialogSize.width() / 2, dialogSize.height() / 2);
//    dlg.move(centerPos);
//    dlg.initDlgData(ddi);
//    dlg.exec();
}

void TDomain::onDelCurrentRec()
{
    QVector<int> rowids;
    QVariantList vvids;
    QString dnIds;
    int totalRowCount = this->m_mainModel->rowCount();
    for (int i = totalRowCount - 1; i >= 0; --i) {
        QModelIndex index = m_mainModel->index(i, 0); // 假设勾选列位于第一列
        if (index.data(Qt::CheckStateRole).toInt() == Qt::Checked) {
            index = m_mainModel->index(i, 1);
            rowids.append(i);
            //qDebug()<<i;
            vvids.append(index.data(Qt::DisplayRole).toInt());
            dnIds+=QString::number(index.data(Qt::DisplayRole).toInt())+",";
        }
    }
    int delnum = rowids.size();
    if(delnum==0)
    {
        QMessageBox::information(this,"提示","请选择要删除的域名");
        return;
    }

    QString infostr ="是否要删除该"+QString::number(delnum)+"条记录:";
    QMessageBox::StandardButton result= QMessageBox::question(this,"提示",infostr);
    if(result==QMessageBox::No)
        return;

    if(!m_dbMySql->deleteDomainRecFromTable(vvids))
    {
        QMessageBox::information(this,"提示","变更域名类别失败");
        return;
    }

    for (int j = 0; j < delnum; j++) {
        m_mainModel->deleteData(rowids.at(j));
    }
    // QModelIndex selectedIndex = m_tableView->selectionModel()->currentIndex();
    // if (!selectedIndex.isValid()) {
    //     QMessageBox::warning(this, "警告", "请选择一条记录删除！");
    //     return;
    // }

    // QStandardItem *itemId = m_tableModel->item(selectedIndex.row(),0);
    // int recId = itemId->text().toInt();

    // QStandardItem *itemName = m_tableModel->item(selectedIndex.row(),1);
    // QString dnStr;
    // QVector<int> rowids;
    // QVariantList vvids;
    // int totalRowCount = m_tableModel->rowCount();
    // for (int i = totalRowCount - 1; i >= 0; --i) {
    //     QModelIndex index = m_tableModel->index(i, 0); // 假设勾选列位于第一列
    //     if (index.data(Qt::CheckStateRole).toInt() == Qt::Checked) {
    //         rowids.append(i);
    //         qDebug()<<i;
    //         vvids.append(index.data(Qt::DisplayRole).toInt());
    //     }
    // }
    // int delnum = rowids.size();
    // if(delnum==0)
    // {
    //     QMessageBox::information(this,"提示","请选择要删除的域名");
    //     return;
    // }
    // QString infostr ="是否要删除该"+QString::number(delnum)+"条记录:";
    // QMessageBox::StandardButton result= QMessageBox::question(this,"提示",infostr);
    // if(result==QMessageBox::No)
    //     return;
    // m_dbMySql->deleteDomainRecFromTable(vvids);
    // totalRowCount=rowids.count();
    // for (int j = 0; j < totalRowCount; j++) {
    //     qDebug()<<rowids.at(j);
    //     m_tableModel->removeRow(rowids.at(j));
    // }

//    QModelIndexList selectedIndexes = ui->tableView->selectionModel()->selectedRows();
//    if (selectedIndexes.isEmpty()) {
//        QMessageBox::warning(this, tr("Warning"), tr("No row selected."));
//        return;
//    }

//    for (const QModelIndex &index : selectedIndexes) {
//        int row = index.row();
//        m_mainModel->removeRow(row);
//        m_dbMySql->deleteDomainRecFromTable(vvids);
//    }
}

void TDomain::onRefleshDomainTable(int categoryId)
{
    onCategorySelected();
}
void TDomain::slotShowToolTip(QModelIndex index)
{
    //qDebug()<<index;
    QToolTip::showText(QCursor::pos(),index.data().toString());

}
void TDomain::onsetDomainsCategory()
{
    //QString dnStr;
    QVector<int> rowids;
    QVariantList vvids;
    QString dnIds;
    int totalRowCount = this->m_mainModel->rowCount();
    for (int i = totalRowCount - 1; i >= 0; --i) {
        QModelIndex index = m_mainModel->index(i, 0); // 假设勾选列位于第一列
        if (index.data(Qt::CheckStateRole).toInt() == Qt::Checked) {
            index = m_mainModel->index(i, 1);
            rowids.append(i);
            //qDebug()<<i;
            vvids.append(index.data(Qt::DisplayRole).toInt());
            dnIds+=QString::number(index.data(Qt::DisplayRole).toInt())+",";
        }
    }
    int delnum = rowids.size();
    if(delnum==0)
    {
        QMessageBox::information(this,"提示","请选择要分类的域名");
        return;
    }

    DnCategorySelectDlg dlg(this);

    int result= dlg.exec();

        if(dlg.m_CategoryId==-1)
            return;
        int categoryId = dlg.m_CategoryId;
        //qDebug() <<categoryId;
        dnIds.chop(1);
        if(!m_dbMySql->updateDnCategory(categoryId,dnIds))
        {
            QMessageBox::information(this,"提示","变更域名类别失败");
            return;
        }
        totalRowCount=rowids.count();
        for (int j = 0; j < totalRowCount; j++) {
           // qDebug()<<rowids.at(j);
            //m_mainModel->removeRow(rowids.at(j));
            m_mainModel->deleteData(rowids.at(j));
        }

}

void TDomain::updateProgress(int progress) {
    // 在这里可以添加任何需要的计算逻辑
    float fraction =100* progress / m_pgBarTotal;
    int prvalue =  qRound(fraction);

    //qDebug() << "返回值"<<progress<<m_pgBarTotal;
    ui->progressBar->setValue(prvalue);
    if(progress ==m_pgBarTotal)
    {
        ui->btn_stopQryDomain->setEnabled(false);
        onCategorySelected();
    }
}

void TDomain::onQryDomainWhois()
{
        //    QModelIndex selectedIndex = m_tableView->selectionModel()->currentIndex();
        //    if (!selectedIndex.isValid()) {
        //        return;
        //    }

        //    QStandardItem *itemId = m_tableModel->item(selectedIndex.row(),1);
        //    QString dnStr = itemId->text();
        //    this->queryDomainWhois(dnStr);
        /***********************************
        QString dnStr;
        int totalRowCount = m_tableModel->rowCount();
        QMap<QString,DomainQryAddrInfo> m_dnMaps;
        //QVector<SocketDnInfo> dnVects;
        m_dnVects.clear();
        for (int i = totalRowCount - 1; i >= 0; --i) {
            QModelIndex index = m_tableModel->index(i, 0); // 假设勾选列位于第一列
            if (index.data(Qt::CheckStateRole).toInt() == Qt::Checked) {

            QModelIndex idx = m_tableModel->index(i, 1);
            dnStr= idx.data(Qt::DisplayRole).toString();
            QString suffix = "."+dnStr.section('.',1,-1);
            int port;
            QStringList strWhois = g_dnSuffixMappingWhoIs[suffix];
            if(strWhois.size()==0)
            {
                qDebug()<<"无法查找到匹配的域名服务器!"<<dnStr;
                return;
            }
            DomainQryAddrInfo dqai;
            dqai.domainSuffix=suffix;
            dqai.qryAddress = strWhois.at(0);
            dqai.port = strWhois.at(1);
            m_dnMaps[dnStr]=dqai;
            SocketDnInfo sdi;
            sdi.msg ="domain "+ dnStr;
            sdi.suffix = suffix;
            sdi.address = strWhois.at(0);
            sdi.port =strWhois.at(1);
            sdi.reqParam = dnStr;
            m_dnVects.append(sdi);
            }
        }
        ***************************************************/
        if(ui->btn_stopQryDomain->isEnabled())
        {
            QMessageBox::information(this,"提示","当前有正在运行的查询，请先终止正在进行的查询！");
            return;
        }
        QMessageBox::StandardButton result= QMessageBox::question(this,"提示","是否启用代理服务器?");
        if(result==QMessageBox::Yes)
        {
            QString proxyStr = g_proxyPool.getNextProxy();
            if (proxyStr.length() == 0) {
                qDebug() << "获取代理失败,无有效代理！";
                return;
            }
            g_enableProxy = true;
            qDebug()<<"启用代理:"<<g_enableProxy;
        }
        else
        {
            g_enableProxy = false;
            qDebug()<<"关闭代理"<<g_enableProxy;
        }
        m_dnVects.clear();
        QString dnStr;
        int domainId;
        int totalRowCount = m_mainModel->rowCount();

  //      for (int i = totalRowCount - 1; i >= 0; --i) {
        for (int i = 0;i<totalRowCount ;i++) {
            QModelIndex idx = m_mainModel->index(i, 1);
            domainId =  idx.data(Qt::DisplayRole).toInt();
            idx = m_mainModel->index(i, 2);
            dnStr= idx.data(Qt::DisplayRole).toString();
            QString suffix = "."+dnStr.section('.',1,-1);
            //qDebug()<<domainId<<dnStr;
            int port;
            QStringList strWhois = g_dnSuffixMappingWhoIs[suffix];
            if(strWhois.size()==0)
            {
                QMessageBox::information(this,"提示","无法查找到匹配的域名服务器!-"+suffix);
                qDebug()<<"无法查找到匹配的域名服务器!"<<dnStr;
                return;
            }
            SocketDnInfo sdi;
            sdi.Id = domainId;
            sdi.msg ="domain "+ dnStr;
            sdi.suffix = suffix;
            sdi.address = strWhois.at(0);
            sdi.port =strWhois.at(1);
            sdi.reqParam = dnStr;
            m_dnVects.append(sdi);
        }
        m_reqMax = m_dnVects.size();

        // for(int p=0;p<m_reqMax;p++)
        //     qDebug()<<m_dnVects[p].Id;
        if(m_reqMax==0)
        {
            QMessageBox::information(this,"提示","请勾选需要查询的域名");
            return;
        }
        requestCounter = 0;
        m_pgBarCurrent =0;
        m_pgBarTotal = m_reqMax;
        g_currentDealNum = 0;
        GlobalQueue* queue = GlobalQueueSingleton::instance();
        queue->clearQueue();
        // 启动后台线程来处理代理列表加载和任务发起

        auto loadDomainQueryTask = new LoadDomainQueryTask(m_dnVects);
        QThread* taskThread = new QThread();
        loadDomainQueryTask->moveToThread(taskThread);

        connect(taskThread, &QThread::started, loadDomainQueryTask, &LoadDomainQueryTask::run);
        connect(loadDomainQueryTask, &LoadDomainQueryTask::taskFinish, loadDomainQueryTask, &QObject::deleteLater);
        connect(loadDomainQueryTask, &LoadDomainQueryTask::taskInterrupt, loadDomainQueryTask, &QObject::deleteLater);
        connect(loadDomainQueryTask, &LoadDomainQueryTask::destroyed, taskThread, &QThread::quit);
        connect(taskThread, &QThread::finished, taskThread, &QThread::deleteLater);
        //connect(this, &TDomain::stopDnQryThread, loadDomainQueryTask, &LoadDomainQueryTask::stopThread);
        connect(this, &TDomain::stopDnQryThread, this, [this, loadDomainQueryTask]() {
            //qDebug() << "TDomain: Invoking stopThread on loadDomainQueryTask";
            loadDomainQueryTask->stopThread();
        });

        //qDebug() <<"in TDomain start loadDomainQueryTask thread ，总记录数："<<m_pgBarTotal;
        taskThread->start();

        auto SqliteWriterTask = new SqliteWriter();
        QThread* sqliteWriterThread = new QThread();
        SqliteWriterTask->moveToThread(sqliteWriterThread);

        connect(sqliteWriterThread, &QThread::started, SqliteWriterTask, &SqliteWriter::run);
        connect(this, &TDomain::stopDnQryThread, this, [this, SqliteWriterTask]() {
            SqliteWriterTask->abnormalStopThread();
        });
        // connect(loadDomainQueryTask, &LoadDomainQueryTask::taskInterrupt, this, [this, SqliteWriterTask]() {
        //     SqliteWriterTask->abnormalStopThread();
        // });
        connect(loadDomainQueryTask, &LoadDomainQueryTask::taskFinish, this, [this, SqliteWriterTask]() {
            SqliteWriterTask->normalStopThread();
        });
        connect(SqliteWriterTask, &SqliteWriter::finishedTask, SqliteWriterTask, &QObject::deleteLater);
        connect(SqliteWriterTask, &SqliteWriter::finishedTask, sqliteWriterThread, &QThread::quit);
        connect(sqliteWriterThread, &QThread::finished, sqliteWriterThread, &QThread::deleteLater);
        connect(SqliteWriterTask, &SqliteWriter::progressChanged,this, &TDomain::updateProgress);
        // connect(SqliteWriterTask, &SqliteWriter::progressChanged,this,[&](int &dealNum){
        //     // ui->progressBar, &QProgressBar::setValue
        //      float fraction =100* dealNum / m_pgBarTotal;
        //     int prvalue =  qRound(fraction);
        //     ui->progressBar->setValue(prvalue);
        // });

        //qDebug() <<  "in TDomain start SqliteWriterTask thread";
        sqliteWriterThread->start();
        ui->btn_stopQryDomain->setEnabled(true);

        // auto loadDomainQueryTask = new LoadDomainQueryTask(m_dnVects);
        // QThread* taskThread = new QThread();
        // loadDomainQueryTask->moveToThread(taskThread);

        // connect(taskThread, &QThread::started, loadDomainQueryTask, &LoadDomainQueryTask::run);
        // connect(this, &TDomain::stopDnQryThread, loadDomainQueryTask, &LoadDomainQueryTask::stopThread);
        // connect(loadDomainQueryTask, &QObject::destroyed, taskThread, &QThread::quit);
        // connect(taskThread, &QThread::finished, taskThread, &QThread::deleteLater);
        // connect(loadDomainQueryTask, &LoadDomainQueryTask::result, this, &TDomain::dealRecvDataFromServer,Qt::QueuedConnection);


        // connect(loadDomainQueryTask, &LoadDomainQueryTask::finished, [&]() {
        //     qDebug()<<__FUNCTION__<<QThread::currentThreadId()<<"finish LoadDomainQueryTask  thread";
        //     // loadDomainQueryTask->setParent(nullptr);
        //     // delete loadDomainQueryTask;
        // });

        // connect(loadDomainQueryTask, &LoadDomainQueryTask::started, this, [this]() {
        //     qDebug()<<__FUNCTION__<<QThread::currentThreadId()<<"start LoadDomainQueryTask  thread";
        // });
        //connect(loadAndValidateTask, &LoadAndValidateProxyTask::progress, this, &ProxyMgrDlg::onProgress);

        // connect(taskThread, &QThread::finished, loadDomainQueryTask, &LoadDomainQueryTask::deleteLater);

       // qDebug()<<__FUNCTION__<<QThread::currentThreadId()<<"in tdmian start loadDomainQueryTask thread";
       //  taskThread->start();

       //  auto  SqliteWriterTask= new SqliteWriter();
       //  QThread* sqliteWriterThread = new QThread();
       //  SqliteWriterTask->moveToThread(sqliteWriterThread);

       //  connect(sqliteWriterThread, &QThread::started, SqliteWriterTask, &SqliteWriter::run);

       //  connect(taskThread, &QThread::finished, SqliteWriterTask,&SqliteWriter::stopThread1);
       //  connect(SqliteWriterTask, &SqliteWriter::finishedTask, sqliteWriterThread, &QThread::quit);
       //  //connect(this, &TDomain::stopSqliteWriteThread, SqliteWriterTask, &SqliteWriter::stopThread1);
       //  //connect(this, &TDomain::stopDnQryThread, SqliteWriterTask, &SqliteWriter::stopThread1);
       //  // connect(SqliteWriterTask, &QObject::destroyed, sqliteWriterThread, &QThread::quit);
       //  // connect(sqliteWriterThread, &QThread::finished, sqliteWriterThread, &QThread::deleteLater);

       //  // connect(this, &TDomain::stopSqliteWriteThread,   [&]() {
       //  //     qDebug()<<"i am here"<<SqliteWriterTask;
       //  //     SqliteWriterTask->stopThread1();
       //  // });
       //  // connect(taskThread, &QThread::finished, SqliteWriterTask, &SqliteWriter::stopThread);

       //  qDebug()<<__FUNCTION__<<QThread::currentThreadId()<<"in tdmian start SqliteWriterTask thread";
       //  sqliteWriterThread->start();

        /*//////定时器方式/////////////////////*/
//        SocketDnInfo sdi = m_dnVects.at(requestCounter);
//        requestTimer = new QTimer(this);
//        connect(requestTimer, &QTimer::timeout, [sdi, this]() {sendNextRequest(sdi);});
//        requestTimer->start(200);
        /*////起线程方式/////////////*/
//        auto runnable = new CTSocketRunnable(m_dnVects);

//        connect(runnable, &CTSocketRunnable::resultReady, this, &TDomain::dealRecvDataFromServer);
//        //runnable->m_dnMaps = m_dnMaps;

//        QThreadPool::globalInstance()->start(runnable);

        //    auto clientSocket = new CTClientSocket();
        //    clientSocket->setServerAddress(addrStr);
        //    clientSocket->setServerPort(port);
        //    clientSocket->setSendMsg(dnStr);
        //    clientSocket->setMsgFlag(dnStr,dnStr);
        //    auto runnable = new CTSocketRunnable(clientSocket, dnStr);
        //    //connect(runnable, &CTSocketRunnable::resultReady, this, &TDomain::dealRecvDataFromServer); // 连接信号与槽
        //    connect(clientSocket, &CTClientSocket::dataSocketReceived, this, [&](QByteArray &data, QString &receivedRequestId){dealRecvDataFromServer(receivedRequestId,data);});
        //    //connect(clientSocket, &CTClientSocket::dataSocketReceived, this, [&](){qDebug()<<344345;});
        //    qDebug()<<111;
        //    m_threadPool->start(runnable);
        //    qDebug()<<222;
        //    QThread::msleep(100);
}
void TDomain::sendNextRequest(SocketDnInfo sdi)
{
//        SocketDnInfo ssd = m_dnVects.at(requestCounter);

//        auto task = new RequestTask(this); // 将MainWindow作为父对象，以便在适当的时候删除RequestTask
//        task->m_address = ssd.address;
//        task->m_sendMsg = ssd.domain;
//        task->m_port = ssd.port.toInt();
//        task->m_reqParam = ssd.reqParam;
//        task->moveToThread(QThreadPool::globalInstance()->thread()); // 将RequestTask移动到工作线程
//        connect(task, &RequestTask::responseReceived, this, &TDomain::dealRecvDataFromServer);
//        connect(task, &QObject::destroyed, this, [this]() {/* qDebug()<<"destroyed";--requestCounter;*/ }); // 当RequestTask被销毁时，递减请求计数器
//        qDebug()<<"QTimer::send msg"<<task->m_reqParam<<task->m_address<<task->m_sendMsg;
//        task->start(); // 调用start槽函数，而非直接启动QRunnable
//        qDebug()<<"QTimer::out";
//        requestCounter++;
//        if (requestCounter >= m_reqMax) {
//            requestTimer->stop();
//            //qDebug()<<"Close QTimer"<<requestCounter;
//            return;
//        }
}

void TDomain::on_actionProxyMgr_triggered()
{
        // 设置对话框的大小
        QSize dialogSize = QSize(size().width() * 0.8, size().height() * 0.8);
        // 居中显示对话框
        QPoint centerPos = geometry().center() - QPoint(dialogSize.width() / 2, dialogSize.height() / 2);
        ProxyMgrDlg *pdlg = new ProxyMgrDlg(this);
        pdlg->setAttribute(Qt::WA_DeleteOnClose);//自动销毁
        pdlg->setWindowTitle("代理服务器管理");
        pdlg->setFixedSize(dialogSize);
        pdlg->move(centerPos);
        pdlg->setWindowFlags(pdlg->windowFlags() & ~Qt::WindowStaysOnTopHint);
        pdlg->show();

}


void TDomain::on_btn_stopQryDomain_clicked()
{
        emit stopDnQryThread();
    ui->btn_stopQryDomain->setEnabled(false);
    // GlobalQueue* queue = GlobalQueueSingleton::instance();
    //  qDebug()<<"获取SQL队列长度:"<<queue->getQueueLen();
}

void TDomain::ShowDnToTableView(int rowid,DomainInfo dninfo)
{
        //"ID"<<"域名"<<"后缀"<<"注册状态"<<"注册商名称"<<"创建时间"<<"过期时间"<<"更新时间"<<"DNS服务器"<<"所有人名称"<<"所有人组织"<<"所有人国家"<<"所有人邮箱"<<"域名状态";
//        m_tableModel->item(rowid, 2)->setText(dninfo.Suffix);       //后缀
//        m_tableModel->item(rowid, 3)->setText(dninfo.RegistStatus); //注册状态
//        QDate currentDate = QDate::currentDate();
//        dninfo.LastQryDate = currentDate.toString("yyyy-MM-dd");
//        m_tableModel->item(rowid, 4)->setText(dninfo.LastQryDate);                 //注册状态
//        m_tableModel->item(rowid, 5)->setText(dninfo.Registrar);                   //注册商名称
//        m_tableModel->item(rowid, 6)->setText(dninfo.CreationDate.left(10));       //创建时间
//        m_tableModel->item(rowid, 7)->setText(dninfo.RegistryExpiryDate.left(10)); //过期时间
//        m_tableModel->item(rowid, 8)->setText(dninfo.UpdatedDate.left(10));        //更新时间
//        m_tableModel->item(rowid, 9)->setText(dninfo.NameServer);                  //DNS服务器
//        m_tableModel->item(rowid, 10)->setText(dninfo.RegistrantName);             //所有人名称
//        m_tableModel->item(rowid, 11)->setText(dninfo.RegistrantOrganization);     //所有人组织
//        m_tableModel->item(rowid, 12)->setText(dninfo.RegistrantCountry);          //所有人国家
//        m_tableModel->item(rowid, 13)->setText(dninfo.RegistrantEmail);            //所有人邮箱
//        m_tableModel->item(rowid, 14)->setText(dninfo.DomainStatus);               //域名状态
        qDebug()<<"ShowDnToTableView1======"<<dninfo.Domain;
        //QModelIndex index;

        m_mainModel->setData(m_mainModel->index(rowid, 2),dninfo.Suffix);       //后缀
        m_mainModel->setData(m_mainModel->index(rowid, 3),dninfo.RegistStatus);
        m_mainModel->setData(m_mainModel->index(rowid, 4),dninfo.LastQryDate);                 //注册状态
        m_mainModel->setData(m_mainModel->index(rowid, 5),dninfo.Registrar);                   //注册商名称
        m_mainModel->setData(m_mainModel->index(rowid, 6),dninfo.CreationDate.left(10));       //创建时间
        m_mainModel->setData(m_mainModel->index(rowid, 7),dninfo.RegistryExpiryDate.left(10)); //过期时间
        m_mainModel->setData(m_mainModel->index(rowid, 8),dninfo.UpdatedDate.left(10));        //更新时间
        m_mainModel->setData(m_mainModel->index(rowid, 9),dninfo.NameServer);                  //DNS服务器
        m_mainModel->setData(m_mainModel->index(rowid, 10),dninfo.RegistrantName);             //所有人名称
        m_mainModel->setData(m_mainModel->index(rowid, 11),dninfo.RegistrantOrganization);     //所有人组织
        m_mainModel->setData(m_mainModel->index(rowid, 12),dninfo.RegistrantCountry);          //所有人国家
        m_mainModel->setData(m_mainModel->index(rowid, 13),dninfo.RegistrantEmail);            //所有人邮箱
        m_mainModel->setData(m_mainModel->index(rowid, 14),dninfo.DomainStatus);               //域名状态
        qDebug()<<"ShowDnToTableView2------"<<dninfo.Domain;
}

void TDomain::onVerticalScrollStopped()
{
        //qDebug() << "onVerticalScrollStopped";
        // 获取当前的滚动条位置
        int firstVisibleRow = m_tableView->verticalScrollBar()->value();
        if (firstVisibleRow < 0) firstVisibleRow = 0;
        int offsetRow = m_tableView->verticalScrollBar()->pageStep();
        int lastVisibleRow = firstVisibleRow + offsetRow;
        // 获取可视区域的尺寸
        // QRect visibleRect = m_tableView->viewport()->rect();

        // // 计算可视区域的起始行和列
        // qDebug()<<m_tableView->verticalScrollBar()->pageStep();
        // int firstVisibleRow = m_tableView->rowAt(/*visibleRect.top() +*/ verticalValue);
        // qDebug()<<verticalValue<<visibleRect<<visibleRect.top()<<firstVisibleRow;
        // if (firstVisibleRow < 0) firstVisibleRow = 0;

        // // 计算可视区域的最后一行，注意检查边界
        // int lastVisibleRow = m_tableView->rowAt(visibleRect.bottom() + verticalValue);
        // if (lastVisibleRow < 0) lastVisibleRow = m_tableView->model()->rowCount() - 1;


        // 获取可视区域的第一列和最后一列
        int firstVisibleColumn = 0;
        int lastVisibleColumn = m_tableView->model()->columnCount() - 1;
        //qDebug()<<firstVisibleRow<<offsetRow<<lastVisibleRow;
       // 获取模型
       QAbstractItemModel *model = m_tableView->model();

       // 更新可视区域的所有数据
        QString  dnIds;
       for (int row = firstVisibleRow; row <= lastVisibleRow; row++) {
           QModelIndex index = model->index(row, 0);
           dnIds+=index.data(Qt::DisplayRole).toString();
           if(row!=lastVisibleRow)
            dnIds+=",";

           // for (int column = firstVisibleColumn; column <= lastVisibleColumn; ++column) {
           //     QModelIndex index = model->index(row, column);
           //     qDebug()<<index.data(Qt::DisplayRole).toString();
           //     // 更新数据的逻辑，这里仅为示例
           //     // 假设model有一个updateData方法
           //     //model->updateData(index, "New Data"); // 根据实际情况调整
           // }
       }
       //qDebug()<<dnIds;
       refreshTableViewByDnId(dnIds);

        // 触发数据变化信号，通知视图数据已更新
        QModelIndex topLeft = m_mainModel->index(firstVisibleRow, firstVisibleColumn);
        QModelIndex bottomRight = m_mainModel->index(lastVisibleRow, lastVisibleColumn);
        m_mainModel->updateRangeData(topLeft, bottomRight);
}

void TDomain::onHorizontalScrollStopped()
{
        qDebug() << "onHorizontalScrollStopped";
        // 获取当前的滚动条位置
        int verticalValue = m_tableView->verticalScrollBar()->value();
        // 获取可视区域的尺寸
        QRect visibleRect = m_tableView->viewport()->rect();

        // 计算可视区域的起始行和列
        int firstVisibleRow = m_tableView->rowAt(visibleRect.top() + verticalValue);
        if (firstVisibleRow < 0) firstVisibleRow = 0;

        // 计算可视区域的最后一行，注意检查边界
        int lastVisibleRow = m_tableView->rowAt(visibleRect.bottom() + verticalValue);
        if (lastVisibleRow < 0) lastVisibleRow = m_tableView->model()->rowCount() - 1;

        // 获取可视区域的第一列和最后一列
        int firstVisibleColumn = 0;
        int lastVisibleColumn = m_tableView->model()->columnCount() - 1;

        //        // 获取模型
        //        QAbstractItemModel *model = m_tableView->model();

        //        // 更新可视区域的所有数据
        //        for (int row = firstVisibleRow; row <= lastVisibleRow; ++row) {
        //            for (int column = firstVisibleColumn; column <= lastVisibleColumn; ++column) {
        //                QModelIndex index = model->index(row, column);
        //                // 更新数据的逻辑，这里仅为示例
        //                // 假设model有一个updateData方法
        //                model->updateData(index, "New Data"); // 根据实际情况调整
        //            }
        //        }

        // 触发数据变化信号，通知视图数据已更新
        QModelIndex topLeft = m_mainModel->index(firstVisibleRow, firstVisibleColumn);
        QModelIndex bottomRight = m_mainModel->index(lastVisibleRow, lastVisibleColumn);
        m_mainModel->updateRangeData(topLeft, bottomRight);
}

